/**
 * The filter namespace
 */
ul.Filter = function(){};

/**
 * EQUALS filter mode display only the logs which level 
 * is equals to the filter level
 */
ul.Filter.EQUALS = true;

/**
 * GREATER_THAN filter mode display all logs which level 
 * is greater or equals than the filter level
 */
ul.Filter.GREATER_THAN = false;

ul.Filter.FilterController = function ( element )
{
	this.element = element;
	this.render();
}
ul.Filter.FilterController.prototype = {
	
	tab:null,
 	tabs:null,
	debugButton:null,
	infoButton:null,
	warnButton:null,
	errorButton:null,
	fatalButton:null,
 	modeSwitch:null,
  	filterLabel:null,
  	buttons:null,
    selectedLevel:1,
 
	tabAdded : function( event )
	{
		this.setTab ( event.source );
	},
 	tabRemoved : function ( event )
	{
		if( event.source )
			this.setTab ( event.source );
	},
 	focusChanged : function ( event )
	{
		this.setTab ( event.source );
	},
 	setTab : function ( tabs )
	{
		this.tabs = tabs;
		this.tab = tabs.getTabUnderFocus();
		
		var mode = this.tab.getFile().getFilterMode();
		var level = this.tab.getFile().getFilterLevel();
		
		this.updateButton( level );
		
		this.modeSwitch.checked = this.tab.getFile().getFilterMode();
		this.filter( this.tab.getElement(), mode, level);
	},
 	updateButton : function ( level )
	{
		removeClass( this.filterLabel, FILTERS[ this.selectedLevel ] );
		removeClass( this.buttons[ this.selectedLevel ], CSS.SELECTED );
		
		this.selectedLevel = level.getValue();
		this.filterLabel.removeChild( this.filterLabel.firstChild );
		this.filterLabel.appendChild( document.createTextNode( level.getName().capitalize() ) );
		
		addClass( this.buttons[ this.selectedLevel ], CSS.SELECTED );
		addClass( this.filterLabel, level );
	},
 	getElement : function ()
	{
		return this.element;
	},
 	render : function ()
	{	
		this.debugButton = $("debugButton");
		this.infoButton  = $("infoButton" );
		this.warnButton  = $("warnButton" );
		this.errorButton = $("errorButton");
		this.fatalButton = $("fatalButton");
		this.filterLabel = $("filterLabel");
		this.modeSwitch  = $("modeSwitch" );
				
		this.setupButton( this.debugButton, DEBUG );
		this.setupButton( this.infoButton,  INFO  );
		this.setupButton( this.warnButton,  WARN  );
		this.setupButton( this.errorButton, ERROR );
		this.setupButton( this.fatalButton, FATAL );
		
		//this.debugButton.parentNode.onmouseout = delegate( this, this.mouseup );
		
		this.buttons =  [ null, this.debugButton, this.infoButton, this.warnButton, this.errorButton, this.fatalButton ];
	},
 	mousepressed:false,
	mouseup:function( e )
	{
		this.mousepressed = false;
	},
	mousedown:function( e, l )
	{
		this.mousepressed = true;
		this.setFilterLevel( l );
	},
	mouseover:function( e, l )
	{
		if( this.mousepressed )
		{
			this.setFilterLevel( l );
		}
	},
	setupButton : function ( button, level )
	{
		button.onmouseup = delegate( this, this.mouseup );
		//button.onmouseout = delegate( this, this.mouseup );
		button.onmousedown = delegate( this, this.mousedown, level );
		button.onmouseover = delegate( this, this.mouseover, level );
	},
 	createFilterModeSwitch : function ( mode )
	{
	 	var check = document.createElement( "input" );
	 	check.type = "checkbox";
		check.id = "filterModeSwitch";
		check.checked = mode;
		check.onclick = delegate( this, function(){ this.setFilterMode( this.modeSwitch.checked ); } );
		
		return check;
 	},
  	createFilterModeLabel : function ()
	{
		var label = document.createElement( "label" );
		label.appendChild ( document.createTextNode ( "Filter by equality" ) );	
		label.htmlFor = "filterModeSwitch";
			
		return label;
	},
 	setFilterLevel : function ( level )
	{
		this.tab.getFile().setFilterLevel( level );
		this.updateButton( level );
		this.filter( this.tabs.getContentElement(), 
					 this.tab.getFile().getFilterMode(), 
					 this.tab.getFile().getFilterLevel() );
	},
	setFilterMode : function ( mode )
	{
		this.tab.getFile().setFilterMode( mode );
		this.filter( this.tabs.getContentElement(), 
					 this.tab.getFile().getFilterMode(), 
					 this.tab.getFile().getFilterLevel() );
					 
		if ( this.modeSwitch.checked != mode )
			this.modeSwitch.checked = mode;
	},
 	increment:function()
	{
		var l = this.selectedLevel+1;
		if( l > 5 )
			l = 1;
		
		this.setFilterLevel( FILTERS[ l ] );
		
	},
	/**
	 * 
	 * @param	element
	 * @param	mode
	 * @param	level
	 */
	filter : function( element, mode, level )
	{
		if( element )
		{
			var x = element.childNodes;
			for (var i = 0 ; i < x.length ; i++ )
			{
				var el = x[i];
				var stringLevel;
				
				if( (stringLevel = el.className.match ( /DEBUG|INFO|WARN|ERROR|FATAL/ ) ) )
				{
					eval( "var numericLevel = " + stringLevel + ".getValue();" );
					
					if( mode )
					{	
						if( numericLevel == level.getValue() )
						{
							removeClass ( el, CSS.HIDDEN );
						}
						else
						{
							addClass ( el, CSS.HIDDEN );
						}
					}
					else
					{
						if( numericLevel >= level.getValue() )
						{
							removeClass ( el, CSS.HIDDEN );
						}
						else
						{
							addClass ( el, CSS.HIDDEN );
						}
					}
				}
			}
		}
	}
}

/**
 * Creates a new filter level for logs filtering.
 * 
 * @param {String} name
 * @param {Number} value
 */
ul.Filter.FilterLevel = function ( name, value )
{
	this.name = name;
	this.value = value;
};
/**
 * FilterLevel prototype declaration
 */
ul.Filter.FilterLevel.prototype = {
	/**
	 * Returns the name of the filter level as a String.
	 * 
	 * @return the name of the filter level as a String
	 */
	getName : function () 
	{ 
		return this.name; 
	},
	/**
	 * Returns the numeric value associated with this
	 * filter level. Values are used to perform comparison
	 * between log levels and filter level.
	 * 
	 * @return 	the numeric value associated with this
	 * 			filter level
	 */
	getValue : function () 
	{ 
		return this.value; 
	},
	/**
	 * Returns the String representation of the object.
	 * 
	 * @return the String representation of the object
	 */
	toString : function () 
	{ 
		return this.getName();
	}
};


/**
 * Defines the ALL filter level which allow message with any levels.
 */
ALL = new ul.Filter.FilterLevel( "ALL", 	0 );
/**
 * Defines the DEBUG filter level.
 */
DEBUG = new ul.Filter.FilterLevel( "DEBUG", 1 );
/**
 * Defines the INFO filter level.
 */
INFO = new ul.Filter.FilterLevel( "INFO", 	2 );
/**
 * Defines the WARN filter level
 */
WARN = new ul.Filter.FilterLevel( "WARN", 	3 );
/**
 * Defines the ERROR filter level
 */
ERROR= new ul.Filter.FilterLevel( "ERROR", 	4 );
/**
 * Defines the FATAL filter level
 */
FATAL = new ul.Filter.FilterLevel( "FATAL", 5 );
/**
 * Defines the NONE filter level which allow no logs of any levels.
 */
NONE = new ul.Filter.FilterLevel( "NONE", 	6 );
/**
 * Allow to retreive a level with its value
 */
FILTERS = [ALL, DEBUG, INFO, WARN, ERROR, FATAL, NONE];
